`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2024/12/16 19:38:08
// Design Name: 
// Module Name: automat
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module automat#(
    parameter DRINK_NUM = 3,  // 可设置饮料种类数量，方便扩容
    parameter MAX_MONEY = 100,  // 可设置最大投入钱数，方便扩容
    parameter A=1,B=2,C=3,  // 确定饮料编号示例，可根据实际扩容修改
    parameter A_price=5,B_price=10,C_price=20  // 简单赋值饮料的价值示例，可扩容修改
)
(
    input clk,
    input rst_n,
    input [5:0] drink,  // 要购买的饮料
    input [10:0] money,  // 投入的钱
    output reg [5:0] drink_out,  // 为0时不投出饮料，为其他编号值时投出对应饮料
    output reg [10:0] balance,  // 余额
    output reg p_balance  // 余额是否充足信号，为0时充足，为1不足
);

    localparam WAIT_INPUT = 2'b00;  // 等待输入状态
    localparam CHECK_MONEY = 2'b01;  // 检查金额状态
    localparam DISPENSE_DRINK = 2'b10;  // 投出饮料状态
    localparam ERROR_STATE = 2'b11;  // 错误状态

    reg [1:0] current_state, next_state;
    reg [5:0] valid_drink;  // 用于存储合法的饮料编号
    reg [10:0] valid_money;  // 用于存储合法的投入钱数

    // 对输入的饮料编号和钱数进行合法性检查
    always @(*) begin
        if (drink >= 1 && drink <= DRINK_NUM) begin
            valid_drink = drink;
        end else begin
            valid_drink = 0;
        end

        if (money >= 0 && money <= MAX_MONEY) begin
            valid_money = money;
        end else begin
            valid_money = 0;
        end
    end

    // 状态转移逻辑
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            current_state <= WAIT_INPUT;
        end else begin
            current_state <= next_state;
        end
    end

    // 根据当前状态和输入决定下一个状态以及输出
    always @(*) begin
       if (!rst_n) begin
       next_state=WAIT_INPUT;
       
      end
        case (current_state)
            WAIT_INPUT: begin
                if (valid_drink!= 0 && valid_money!= 0) begin
                    next_state = CHECK_MONEY;
                end
            end
            CHECK_MONEY: begin
                if (valid_drink == A && valid_money >= A_price) begin
                    next_state = DISPENSE_DRINK;
                    p_balance = 0;
                end else if (valid_drink == B && valid_money >= B_price) begin
                    next_state = DISPENSE_DRINK;
                    p_balance = 0;
                end
                else if (valid_drink == C && valid_money >= C_price) begin
                    next_state = DISPENSE_DRINK;
                    p_balance = 0;
                end
                   else begin
                    next_state = ERROR_STATE;
                    p_balance =1;
                    drink_out=0;
                end
            end
            DISPENSE_DRINK: begin
                drink_out = valid_drink;
                if (valid_drink == A) begin
                    balance = valid_money - A_price;
                end 
              else if (valid_drink == B) begin
                    balance = valid_money - B_price;
                end
               else if (valid_drink == C) begin
                    balance = valid_money - C_price;
                end
                next_state = WAIT_INPUT;
            end
            ERROR_STATE: begin
                balance = valid_money;
                next_state = WAIT_INPUT;
            end
            default: begin
                next_state = WAIT_INPUT;
            end
        endcase
    end

endmodule